/*
 * Created on Jul 13, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package clustering.implementations;
import java.util.ArrayList;
import java.util.Hashtable;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import clustering.framework.*;
import clustering.testing.Debug;

/**
 * @author Administrator
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class QuartetErrorsTreeScorer implements IClusterTreeScorer{
	QNode [] qNodes = null;
    Hashtable htPath = null;
    public ArrayList consistentQuartets = null;
	public double ComputeScore(Document xmlTree, double [][] dMatrix){
		qNodes = new QNode[2*dMatrix.length-2];
        ArrayList alQuartets = Quartet.generateFullQuartetList(dMatrix);
        QuartetTree qt = constructFromXmlDocument(xmlTree);
        ArrayList alBestQuartets = Quartet.generateBestQuartetList(dMatrix);
        //qt.M = Quartet.worst_cost.doubleValue();
        //qt.m = Quartet.best_cost.doubleValue();
        int consistent = 0;
        htPath = new Hashtable();;
        consistentQuartets = new ArrayList();
        //double Ct = 0;
        for(int i=0;i<alBestQuartets.size();i++){
            Quartet q = (Quartet)alBestQuartets.get(i);
            if(isConsistent(q,qt)){
     //         Ct += q.weight;
                consistent++;
                consistentQuartets.add(q);
            }
        }
        return 100*(double)consistent/(double)alBestQuartets.size();
	}
	int node_count;
    QuartetTree constructFromXmlDocument(Document xmlTree){
        QuartetTree qt = new QuartetTree();
        QNode qn = new QNode(-1,null,null,null,-1);
        Node xmlNode = xmlTree.getFirstChild();
        node_count = 0;
        for(int i=0;i<xmlNode.getChildNodes().getLength();i++){
			generateTree(xmlNode.getChildNodes().item(i),qn);
		}
        if(xmlNode.getChildNodes().getLength()==2){
		    QNode n1 = qn.adj[0];
		    QNode n2 = qn.adj[1];
		    n1.adj[0] = n2;
		    n2.adj[0] = n1;
		    qt.root = n1;
		}else{
		    qNodes[node_count++]=qn;
		    qt.root = qn;
		}        
        return qt;
    }
    void generateTree(Node xmlNode, QNode n0){
        String sId = xmlNode.getAttributes().getNamedItem("id").getNodeValue();
		int id = Integer.parseInt(sId);
		QNode qn = new QNode(id,n0,null,null,-1);
		if(n0.adj[0]==null)n0.adj[0]=qn;
		else if(n0.adj[1]==null)n0.adj[1]=qn;
		else n0.adj[2]=qn;
		if(xmlNode.hasChildNodes()){
			for(int i=0;i<xmlNode.getChildNodes().getLength();i++){
				generateTree(xmlNode.getChildNodes().item(i),qn);
			}			
		}
		qNodes[node_count++]=qn;
	}
    boolean isConsistent(Quartet q, QuartetTree qt){
        QNode a = getNodeByLabel(q.nodes[0]);
        QNode b = getNodeByLabel(q.nodes[1]);
        QNode c = getNodeByLabel(q.nodes[2]);
        QNode d = getNodeByLabel(q.nodes[3]);
        if(htPath.get(a)==null){
        	htPath.put(a,qt.Dijkstra(a,qNodes));
        }
        if(htPath.get(b)==null){
        	htPath.put(b,qt.Dijkstra(b,qNodes));
        }
        if(htPath.get(c)==null){
        	htPath.put(c,qt.Dijkstra(c,qNodes));
        }
        if(htPath.get(d)==null){
        	htPath.put(d,qt.Dijkstra(d,qNodes));
        }
        ArrayList path1 = (ArrayList)((Hashtable)htPath.get(a)).get(b);
        ArrayList path2 = (ArrayList)((Hashtable)htPath.get(c)).get(d);
        for(int i=1;i<path1.size()-1;i++){
            QNode qn1 = (QNode)path1.get(i);
            for(int j=1;j<path2.size()-1;j++){
                QNode qn2 = (QNode)path2.get(j);
                if(qn1 == qn2)return false;
            }
        }
        return true;
    }
    QNode getNodeByLabel(int label){
        for(int i=0;i<qNodes.length;i++){
            QNode qn = qNodes[i];
            if(qn.label == label)return qn;
        }
        return null;
    }
}
